import {
  Injectable,
  UnauthorizedException,
  ConflictException,
} from '@nestjs/common';
import { JwtService } from '@nestjs/jwt';
import { InjectRepository } from '@nestjs/typeorm';
import { Repository } from 'typeorm';
import * as bcrypt from 'bcrypt';
import { LoginDto } from './dto/login.dto';
import { RegisterDto } from './dto/register.dto';
import { User } from './entity/user.entity';

@Injectable()
export class AuthService {
  constructor(
    @InjectRepository(User)
    private readonly userRepository: Repository<User>,
    private readonly jwtService: JwtService,
  ) {}

  // 用户注册
  async register(registerDto: RegisterDto): Promise<Partial<User>> {
    // 检查密码是否一致
    if (registerDto.password !== registerDto.confirmPassword) {
      throw new UnauthorizedException('两次输入的密码不一致');
    }

    // 检查用户名或邮箱是否已存在
    const existingUser = await this.userRepository.findOne({
      where: [{ username: registerDto.username }, { email: registerDto.email }],
    });

    if (existingUser) {
      throw new ConflictException('用户名或邮箱已被注册');
    }

    // 加密密码
    const salt = await bcrypt.genSalt();
    const hashedPassword = await bcrypt.hash(registerDto.password, salt);

    // 创建新用户
    const newUser = this.userRepository.create({
      username: registerDto.username,
      email: registerDto.email,
      password: hashedPassword,
      role: 'user',
    });

    // 保存用户到数据库
    await this.userRepository.save(newUser);

    // 返回用户信息（不包含密码）
    const { ...result } = newUser;
    return result;
  }

  // 用户登录
  async login(
    loginDto: LoginDto,
  ): Promise<{ accessToken: string; user: Partial<User> }> {
    // 查找用户
    const user = await this.userRepository.findOne({
      where: { username: loginDto.username },
    });

    // 验证用户和密码
    if (!user || !(await bcrypt.compare(loginDto.password, user.password))) {
      throw new UnauthorizedException('用户名或密码错误');
    }

    // 创建JWT载荷
    const payload = {
      id: user.id,
      username: user.username,
      role: user.role,
    };

    const accessToken = this.jwtService.sign(payload);
    const { ...userInfo } = user;
    return { accessToken, user: userInfo };
  }

  // 根据ID验证用户
  async validateUserById(id: number): Promise<Partial<User> | null> {
    const user = await this.userRepository.findOne({
      where: { id },
    });
    if (!user) {
      return null;
    }
    const { ...userInfo } = user;
    return userInfo;
  }
}
